package com.cskaoyan.javase.oop2._2polymorphic._3exercise;

/**
 * 读程序题
 * 首先查看对象名点成员方法
 * 要记住引用决定了访问范围:
 *      如果是父类引用,就不要看子类了,除非指向的对象是子类,就需要看子类是否重写方法
 *      如果是子类引用,那就同时需要看父类加子类
 *
 * @since 15:51
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo2 {
    public static void main(String[] args) {
        // 父类引用指向父类对象,这个引用a1和子类没有任何关系,全程只需要看A类即可.
        A a1 = new A();
        // 父类引用指向子类对象,这时引用的访问范围仍然是父类,但是一旦这个方法在子类中重写,那么就要体现出子类的行为
        A a2 = new B();
        // 子类引用指向子类对象,这时引用的访问范围是父类+子类
        B b = new B();
        C c = new C();
        D d = new D();
        System.out.println("1--" + a1.show(b)); // AA
        System.out.println("2--" + a1.show(c)); // AA
        // 这里能够同时匹配A类中的两个方法,但是就近原则,优先选择恰好匹配的,不需要类型转换的方法
        System.out.println("3--" + a1.show(d)); // AD

        System.out.println("4--" + a2.show(b)); // BA
        // c对象是B的直接子类对象,是A的间接子类对象,所以应该匹配B,就近原则
        System.out.println("5--" + a2.show(c)); // BA
        System.out.println("6--" + a2.show(d)); // AD

        System.out.println("7--" + b.show(b)); // BB
        System.out.println("8--" + b.show(c)); // BB
        System.out.println("9--" + b.show(d)); // AD
    }
}
class A {
    // 父类中独有的方法
    public String show(D obj) {
        return ("A and D");
    }
    // 父子类中,子类重写了父类的方法
    public String show(A obj) {
        return ("A and A");
    }
}
class B extends A {
    // 子类中独有的方法
    public String show(B obj) {
        return ("B and B");
    }
    // 父子类中,子类重写了父类的方法
    @Override
    public String show(A obj) {
        return ("B and A");
    }
}
class C extends B {
}
class D extends B {
}